﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Leeder.Logger;

namespace NewAndong.Handle
{
    public class TcpIpServer
    {
        private LogOperate LogObj => Log.GetLogger(this.GetType());

        Socket serverSocket; // 服务器端Socket，用于服务器与客户端的通信
        Socket clientSocket; // 客户端Socket，用于与客户端建立连接
        TcpListener tcpListener; // 负责监听客户端的连接请求
        Thread tcpListenerThread; // 监听连接请求的线程
        Dictionary<string, Socket> dicClientSockets = new Dictionary<string, Socket>(); // 存储客户端Socket的集合，以客户端的IP/端口作为键
        Dictionary<string, Thread> dicReceiveMsg = new Dictionary<string, Thread>(); // 存储每个客户端接收消息的线程集合

        string _IP; // 服务器的IP地址
        int _Port; // 服务器的端口
        IPAddress _ipAddress; // 服务器的IPAddress对象
        EndPoint _endPoint; // 服务器的端点，包括IP地址和端口
        bool linked = false; // 标识服务器是否已开始监听客户端连接
        bool unlinked = false; // 标识服务器是否已关闭连接

        // 构造函数，初始化服务器的IP和端口
        public TcpIpServer(string ip, int port)
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 初始化Socket对象，使用TCP协议
            _IP = ip;
            _Port = port;
            _ipAddress = IPAddress.Parse(ip); // 将IP地址字符串转换为IPAddress对象
            _endPoint = new IPEndPoint(_ipAddress, port); // 构造服务器端点
        }

        // 判断服务器是否已绑定到指定的端口
        private bool _IsBound;
        public bool IsBound
        {
            get { return _IsBound = serverSocket.IsBound; }
        }

        // 判断服务器Socket是否已连接
        private bool _Connected;
        public bool Connected
        {
            get { return _Connected = serverSocket.Connected; }
        }

        // 绑定服务器并开始监听客户端连接
        public bool Bind(ref string msg)
        {
            try
            {
                if (!linked)
                {
                    tcpListener = new TcpListener(_ipAddress, _Port); // 创建TcpListener对象，绑定IP和端口
                    tcpListener.Start(); // 启动监听
                    linked = true; // 标记已开始监听
                    ThreadStart threadStart = new ThreadStart(ListenConnectRequest); // 创建一个委托，执行监听连接请求的方法
                    tcpListenerThread = new Thread(threadStart); // 创建一个新线程来监听客户端请求
                    tcpListenerThread.IsBackground = true; // 设置为后台线程
                    tcpListenerThread.Start(); // 启动监听线程
                    msg = $"[Info] 服务器{tcpListener.LocalEndpoint.ToString()}监听成功！"; // 返回监听成功的消息
                    return true;
                }
                else
                {
                    msg = $"[Info] 已监听"; // 如果已经开始监听，则返回已监听消息
                    return true;
                }
            }
            catch (Exception ex)
            {
                msg = $"[Err] 连接失败！信息={ex}"; // 如果发生异常，返回错误信息
                return false;
            }
        }

        // 断开与指定客户端的连接
        public bool DisConnectClient(string client, ref string msg)
        {
            try
            {
                if (dicClientSockets.ContainsKey(client))
                {
                    dicClientSockets[client].Close(); // 关闭与客户端的连接
                    msg = $"[Info] 断开客户端{client}连接"; // 返回断开成功的消息
                    return true;
                }
                else
                {
                    msg = $"[Info] 客户端{client}已断开"; // 如果客户端已断开，返回已断开消息
                    return true;
                }
            }
            catch (Exception ex)
            {
                msg = $"[Err] 断开失败！信息={ex}"; // 如果发生异常，返回错误信息
                return false;
            }
        }

        // 关闭服务器监听并断开所有客户端连接
        public bool ShutDown(string[] clientList, ref string msg)
        {
            try
            {
                if (linked)
                {
                    linked = false; // 标记服务器停止监听
                    tcpListener.Stop(); // 停止TcpListener监听
                    for (int i = 0; i < clientList.Length; i++)
                    {
                        dicClientSockets[clientList[i]].Close(); // 关闭每个客户端的连接
                    }
                    msg = $"[Info] 服务器监听断开"; // 返回关闭监听的消息
                    return true;
                }
                else
                {
                    unlinked = true; // 标记已断开
                    msg = $"[Info] 已断开"; // 返回已断开消息
                    return true;
                }
            }
            catch (Exception ex)
            {
                tcpListener.Stop(); // 停止TcpListener
                unlinked = true; // 标记已断开
                msg = $"[Info] 已断开!!!"; // 返回关闭连接的消息
                return false;
            }
        }

        // 向指定客户端发送数据
        public bool SendToClient(string client, string cmd, ref string msg)
        {
            try
            {
                if (!string.IsNullOrEmpty(cmd))
                {
                    dicClientSockets[client].Send(Encoding.UTF8.GetBytes(cmd)); // 将命令数据发送给客户端
                    msg = $"[Info] 发送{client}信息={cmd}"; // 返回发送成功的消息
                    return true;
                }
                else
                    return false; // 如果命令为空，返回发送失败
            }
            catch (Exception ex)
            {
                msg = $"[Err] 发送信息失败！信息={ex}"; // 如果发送失败，返回错误信息
                return false;
            }
        }

        // 向指定客户端发送数据
        public bool SendToAllClient(string cmd)
        {
            try
            {
                if (!string.IsNullOrEmpty(cmd))
                {
                    foreach(var socket in dicClientSockets)
                    {
                        socket.Value.Send(Encoding.UTF8.GetBytes(cmd)); // 将命令数据发送给客户端
                        //msg = $"[Info] 发送{client}信息={cmd}"; // 返回发送成功的消息
                        LogObj.Debug($"[Info] 发送{socket.Key}信息={cmd}");
                    }
                    return true;
                }
                else
                    return false; // 如果命令为空，返回发送失败
            }
            catch (Exception ex)
            {
                //msg = $"[Err] 发送信息失败！信息={ex}"; // 如果发送失败，返回错误信息
                LogObj.Error($"[Err] 发送信息失败！信息={ex}");
                return false;
            }
        }

        // 监听客户端的连接请求
        private void ListenConnectRequest()
        {
            while (linked)
            {
                try
                {
                    Socket clientSocket = tcpListener.AcceptSocket(); // 等待并接受客户端连接
                    ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(ReceiveData); // 创建接收数据的线程委托
                    Thread receiveMsgThread = new Thread(parameterizedThreadStart); // 创建一个线程来接收客户端数据
                    receiveMsgThread.IsBackground = true; // 设置为后台线程
                    receiveMsgThread.Start(clientSocket); // 启动线程并传入客户端Socket
                    dicClientSockets.Add(clientSocket.RemoteEndPoint.ToString(), clientSocket); // 将客户端Socket加入字典
                    dicReceiveMsg.Add(clientSocket.RemoteEndPoint.ToString(), receiveMsgThread); // 将接收消息线程加入字典
                    //Form_Server._AddListEvent(clientSocket.RemoteEndPoint.ToString()); // 更新UI列表，显示已连接的客户端
                    LogObj.Info(clientSocket.RemoteEndPoint.ToString() + "连接成功");
                }
                catch (Exception ex)
                {
                    //Form_Server._ShowServerLogEvent($"[Err] 监听失败！信息={ex}"); // 监听失败时显示错误日志
                    LogObj.Error($"[Err] 监听失败！信息={ex}");

                }
            }
        }

        // 接收客户端发送的数据
        public void ReceiveData(Object obj)
        {
            Socket clientSocket = (Socket)obj; // 将传入的参数转换为Socket
            string str = clientSocket.RemoteEndPoint.ToString(); // 获取客户端的远程端点（IP+端口）
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[1024 * 1024]; // 创建缓存区，大小为1MB
                    int length = clientSocket.Receive(buffer); // 接收客户端数据
                    string message = Encoding.UTF8.GetString(buffer, 0, length); // 将字节数组转换为字符串
                    if (length != 0)
                    {
                        //Form_Server._ShowServerLogEvent($"[Info] 接收客户端{clientSocket.RemoteEndPoint}信息={message}"); // 显示接收到的消息

                        if (message == "ping")
                        {
                            clientSocket.Send(Encoding.UTF8.GetBytes("pong"));
                            //AddSendQueue(clientSocket, "pong");
                        }else
                        {

                            LogObj.Debug($"[Info] 接收客户端{clientSocket.RemoteEndPoint}信息={message}");

                        }
                    }
                }
                catch (Exception)
                {
                    //Form_Server._RemoveListEvent(str); // 从UI列表中移除已断开的客户端
                    dicClientSockets.Remove(str); // 从客户端字典中移除该客户端的Socket
                    dicReceiveMsg.Remove(str); // 从接收消息线程字典中移除该客户端的线程
                    break; // 退出接收数据的循环
                }
            }
        }
    }
}
